﻿using System;
using System.Collections.Generic;
using System.Linq;
using NLite.Collections;

namespace NLite.Messaging.Internal
{
    [Serializable]
    partial class Subscriber : ISubscriber
    {
        private readonly IMap<IObserverHandler<IMessage>,SubscribeMode> observers;
       
        public Subscriber()
        {
            this.observers = new ConcurrentMap<IObserverHandler<IMessage>, SubscribeMode>();
        }

        public string Name { get; set; }
        public IMessageListenerManager ListnerManager { get; set; }

        public IDisposable Subscribe(SubscribeMode mode, IObserverHandler<IMessage> handler)
        {
            if (handler == null
               || observers.ContainsKey(handler))
                return Disposable.Empty;

            var observer = handler.Target;

            //ListnerManager.OnObserverAdding(observer, Name, Type);
            observers.Add(handler,mode);
            //ListnerManager.OnObserverAdded(observer, Name, Type);

            return Disposable.Create(() => Unsubscribe(handler));
        }
 
        public void Unsubscribe(IObserverHandler<IMessage> handler)
        {
            if (handler == null
                || !observers.ContainsKey(handler))
                return;

            //ListnerManager.OnObserverRemoving(handler.Target, Name, Type);
            observers.Remove(handler);
            //ListnerManager.OnObserverRemoved(handler.Target, Name, Type);
        }

        IDictionary<IObserverHandler<IMessage>, SubscribeMode> ISubscriber.Observers
        {
            get
            {
                return new Dictionary<IObserverHandler<IMessage>,SubscribeMode>(observers);
            }
        }
       
        public void Clear()
        {
            var items = observers.ToArray();
            if (items != null && items.Length > 0)
                for (int i = 0; i < items.Length; i++)
                {
                    var dis = items[i].Key as IDisposable;
                    if (dis != null)
                        dis.Dispose();
                    else
                    {
                        var handler = items[i].Key.GetType().GetField("InnerHandler", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                        if (handler != null)
                            handler = null;
                    }
                }

            observers.Clear();  
        }
    }
}
